﻿using Acme.BookStore.FormWhx.Binlocation;
using Acme.BookStore.FormWhx.Storehouse;
using Acme.BookStore.FormWhxDto.BinlocationDto;
using Acme.BookStore.Purchase.Customergoods;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
//using Volo.Abp.Application.Exceptions;
using Volo.Abp.Application.Services;
using Volo.Abp.Caching;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Identity;
using Volo.Abp.Uow;

namespace Acme.BookStore.FormWhxDto.StorehouseDto
{
    public class StorehouseService : CrudAppService
        <SorehouseModels, StorehouseDto, Guid, PagedAndSortedResultRequestDto, CreateUpdateStorehouseDto>, IStorehouseService
    {
        private readonly IRepository<IdentityUser,Guid> _userRepository;
        private readonly IDistributedCache<PagedResultDto<StorehouseDto>,string> _storehouseCache;
        private readonly ILogger<StorehouseService> _logger;
        private readonly IRepository<SorehouseModels, Guid> _repository;
        private readonly IRepository<ManagementDeptModel, int> _deptRepository;
        private readonly IRepository<WarehouseManagerModel, int> _managerRepository;
        private readonly IRepository<locationModel, Guid> _locationRepository;
        private readonly IUnitOfWorkManager _unitOfWorkManager;
        private readonly IWarehouseOperationLogService _operationLogService;

        public StorehouseService
            (
             IRepository<SorehouseModels, Guid> repository,
             IRepository<IdentityUser, Guid> userRepository,
             IDistributedCache<PagedResultDto<StorehouseDto>, string> storehouseCache,
             ILogger<StorehouseService> logger,
             IRepository<ManagementDeptModel, int> deptRepository,
             IRepository<WarehouseManagerModel, int> managerRepository,
             IRepository<locationModel, Guid> locationRepository,
             IUnitOfWorkManager unitOfWorkManager,
             IWarehouseOperationLogService operationLogService)
            : base(repository)
        {
            _userRepository = userRepository;
            _storehouseCache = storehouseCache;
            _logger = logger;
            _repository = repository;
            _deptRepository = deptRepository;
            _managerRepository = managerRepository;
            _locationRepository = locationRepository;
            _unitOfWorkManager = unitOfWorkManager;
            _operationLogService = operationLogService;
        }

        public async Task<List<WarehouseNameDtozmy>> GetWarehouseNamesAsync()
        {
            var list = await _repository.GetListAsync();
            return list.Select(x => new WarehouseNameDtozmy
            {
                Id = x.Id,
                WarehouseName = x.WarehouseName
            }).ToList();
        }

        public async Task<List<ManagementDeptDto>> GetManagementDeptTreeAsync()
        {
            var departments = await _deptRepository.GetListAsync();
            var dtos = ObjectMapper.Map<List<ManagementDeptModel>, List<ManagementDeptDto>>(departments);
            return BuildDeptTree(dtos);
        }

        public async Task<List<ManagementDeptDto>> GetManagementDeptChildrenAsync(int parentId)
        {
            var queryable = await _deptRepository.GetQueryableAsync();
            var query = queryable
                .Where(x => x.ParentId == parentId && x.IsActive)
                .OrderBy(x => x.Sort);

            var children = await AsyncExecuter.ToListAsync(query);

            return ObjectMapper.Map<List<ManagementDeptModel>, List<ManagementDeptDto>>(children);
        }

        public async Task<PagedResultDto<ManagementDeptDto>> SearchManagementDeptAsync(ManagementDeptSearchDto input)
        {
            var queryable = await _deptRepository.GetQueryableAsync();

            var query = queryable
                .WhereIf(!string.IsNullOrWhiteSpace(input.Keyword), x =>
                    x.Code.Contains(input.Keyword) ||
                    x.Name.Contains(input.Keyword))
                .WhereIf(input.ParentId.HasValue, x => x.ParentId == input.ParentId)
                .WhereIf(input.OnlyActive, x => x.IsActive);

            var totalCount = await AsyncExecuter.CountAsync(query);

            var departments = await AsyncExecuter.ToListAsync(
                query.OrderBy(input.Sorting ?? nameof(ManagementDeptModel.Sort))
                    .Skip(input.SkipCount)
                    .Take(input.MaxResultCount)
            );

            var dtos = ObjectMapper.Map<List<ManagementDeptModel>, List<ManagementDeptDto>>(departments);

            return new PagedResultDto<ManagementDeptDto>(totalCount, dtos);
        }

        public async Task<ListResultDto<WarehouseManagerDto>> GetWarehouseManagerAsync()
        {
            var managers = await _managerRepository.GetListAsync();
            return new ListResultDto<WarehouseManagerDto>(
                ObjectMapper.Map<List<WarehouseManagerModel>, List<WarehouseManagerDto>>(managers)
            );
        }

        public async Task<ListResultDto<WarehouseManagerDto>> SearchWarehouseManagerAsync(string keyword)
        {
            var queryable = await _managerRepository.GetQueryableAsync();
            var query = queryable.AsNoTracking();

            if (!string.IsNullOrWhiteSpace(keyword))
            {
                query = query.Where(x => x.Name.Contains(keyword));
            }

            var managers = await AsyncExecuter.ToListAsync(query);
            
            return new ListResultDto<WarehouseManagerDto>(
                ObjectMapper.Map<List<WarehouseManagerModel>, List<WarehouseManagerDto>>(managers)
            );
        }

        private List<ManagementDeptDto> BuildDeptTree(List<ManagementDeptDto> departments)
        {
            // 创建一个字典来存储每个部门的子部门
            var childrenMap = new Dictionary<int, List<ManagementDeptDto>>();
            
            // 初始化字典
            foreach (var dept in departments)
            {
                childrenMap[dept.Id] = new List<ManagementDeptDto>();
            }
            
            // 找出所有根节点（ParentId为0的节点）
            var rootNodes = departments.Where(d => d.ParentId == 0).ToList();
            
            // 构建树形结构
            foreach (var dept in departments.Where(d => d.ParentId != 0))
            {
                if (dept.ParentId.HasValue && childrenMap.ContainsKey(dept.ParentId.Value))
                {
                    childrenMap[dept.ParentId.Value].Add(dept);
                }
            }
            
            // 设置每个部门的Children属性
            foreach (var dept in departments)
            {
                dept.Children = childrenMap[dept.Id];
            }
            
            return rootNodes;
        }

        /// <summary>
        /// 高级查询仓库信息
        /// </summary>
        public async Task<PagedResultDto<StorehouseDto>> SearchAsync(StorehouseSearchDto input)
        {
            try
            {
                // 构建查询
                var query = await _repository.GetQueryableAsync();

                // 应用筛选条件
                if (!string.IsNullOrWhiteSpace(input.WarehouseCode))
                {
                    query = query.Where(x => x.WarehouseCode.Contains(input.WarehouseCode));
                }

                if (!string.IsNullOrWhiteSpace(input.WarehouseName))
                {
                    query = query.Where(x => x.WarehouseName.Contains(input.WarehouseName));
                }

                if (input.MinCapacity.HasValue)
                {
                    query = query.Where(x => x.WarehouseCapacity >= input.MinCapacity.Value);
                }

                if (input.MaxCapacity.HasValue)
                {
                    query = query.Where(x => x.WarehouseCapacity <= input.MaxCapacity.Value);
                }

                if (!string.IsNullOrWhiteSpace(input.ManagementDept))
                {
                    query = query.Where(x => x.ManagementDept.Contains(input.ManagementDept));
                }

                if (!string.IsNullOrWhiteSpace(input.WarehouseManager))
                {
                    query = query.Where(x => x.WarehouseManager.Contains(input.WarehouseManager));
                }

                if (input.MinLocationCount.HasValue)
                {
                    query = query.Where(x => x.LocationCount >= input.MinLocationCount.Value);
                }

                if (input.MaxLocationCount.HasValue)
                {
                    query = query.Where(x => x.LocationCount <= input.MaxLocationCount.Value);
                }

                if (!string.IsNullOrWhiteSpace(input.WarehouseStatus))
                {
                    query = query.Where(x => x.WarehouseStatus == input.WarehouseStatus);
                }

                if (input.OperationTimeStart.HasValue)
                {
                    query = query.Where(x => x.CreationTime >= input.OperationTimeStart.Value);
                }

                if (input.OperationTimeEnd.HasValue)
                {
                    query = query.Where(x => x.CreationTime <= input.OperationTimeEnd.Value);
                }

                if (!string.IsNullOrWhiteSpace(input.Operator))
                {
                    var operatorUser = await _userRepository.FirstOrDefaultAsync(u => u.UserName == input.Operator);
                    if (operatorUser != null)
                    {
                        query = query.Where(x => x.CreatorId == operatorUser.Id);
                    }
                }

                // 获取总数
                var totalCount = await query.CountAsync();

                // 排序和分页
                query = query.OrderBy(input.Sorting ?? "creationTime desc")
                           .Skip(input.SkipCount)
                           .Take(input.MaxResultCount);

                // 执行查询
                var items = await AsyncExecuter.ToListAsync(query);

                // 转换为DTO
                var dtos = ObjectMapper.Map<List<SorehouseModels>, List<StorehouseDto>>(items);

                return new PagedResultDto<StorehouseDto>(totalCount, dtos);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error occurred while searching warehouses");
                throw;
            }
        }

        public override async Task<StorehouseDto> CreateAsync(CreateUpdateStorehouseDto input)
        {
            var warehouse = await base.CreateAsync(input);

            // 记录操作日志
            await _operationLogService.LogOperationAsync(
                "新增",
                $"新增仓库：{input.WarehouseName}",
                warehouse.Id,
                warehouse.WarehouseCode,
                warehouse.WarehouseName
            );

            return warehouse;
        }

        public override async Task<StorehouseDto> UpdateAsync(Guid id, CreateUpdateStorehouseDto input)
        {
            var warehouse = await base.UpdateAsync(id, input);

            // 记录操作日志
            await _operationLogService.LogOperationAsync(
                "修改",
                $"修改仓库信息：{input.WarehouseName}",
                warehouse.Id,
                warehouse.WarehouseCode,
                warehouse.WarehouseName
            );

            return warehouse;
        }

        public async Task AddSorehouseWithLocations(CreateUpdateStorehouseWithLocationsDto input)
        {
            using (var uow = _unitOfWorkManager.Begin(requiresNew: true))
            {
                try
                {
                    // 1. 创建仓库实体
                    var sorehouse = new SorehouseModels(
                        GuidGenerator.Create(),
                        input.Storehouse.WarehouseCode,
                        input.Storehouse.WarehouseName,
                        input.Storehouse.WarehouseCapacity ?? 0,
                        input.Storehouse.WarehouseAddress ?? string.Empty,
                        input.Storehouse.ManagementDept ?? string.Empty,
                        input.Storehouse.WarehouseManager ?? string.Empty,
                        input.Locations?.Count ?? 0,
                        input.Storehouse.WarehouseStatus ?? "正常",
                        input.Storehouse.Phone ?? string.Empty,
                        input.Storehouse.Sort ?? 0,
                        input.Storehouse.IsLocked ?? false,
                        input.Storehouse.Remarks ?? string.Empty
                    );

                    // 2. 保存仓库
                    await _repository.InsertAsync(sorehouse);

                    // 3. 新增库位
                    if (input.Locations != null && input.Locations.Count > 0)
                    {
                        foreach (var locDto in input.Locations)
                        {
                            var location = new locationModel(
                                GuidGenerator.Create(),
                                locDto.LocationId,
                                locDto.LocationName,
                                locDto.Capacity,
                                locDto.Supervisor ?? string.Empty,
                                locDto.Status,
                                locDto.SortOrder,
                                locDto.Remarks ?? string.Empty,
                                sorehouse.Id
                            );

                            await _locationRepository.InsertAsync(location);
                        }
                    }

                    // 4. 记录操作日志
                    await _operationLogService.LogOperationAsync(
                        "新增",
                        $"新增仓库：{sorehouse.WarehouseName}，包含{input.Locations?.Count ?? 0}个库位",
                        sorehouse.Id,
                        sorehouse.WarehouseCode,
                        sorehouse.WarehouseName
                    );

                    await uow.CompleteAsync();
                }
                catch (Exception ex)
                {
                    await uow.RollbackAsync();
                    _logger.LogError(ex, "创建仓库和库位时发生错误: {Message}", ex.Message);
                    throw new UserFriendlyException($"创建仓库和库位失败: {ex.Message}");
                }
            }
        }

        /// <summary>
        /// 更新仓库状态
        /// </summary>
        public async Task<StorehouseDto> UpdateStatusAsync(UpdateStorehouseStatusDto input)
        {
            var warehouse = await _repository.GetAsync(input.Id);
            if (warehouse == null)
            {
                throw new UserFriendlyException($"未找到ID为 {input.Id} 的仓库");
            }

            warehouse.WarehouseStatus = input.Status;
            await _repository.UpdateAsync(warehouse);

            // 记录状态更新操作日志
            await _operationLogService.LogOperationAsync(
                "修改状态",
                $"修改仓库状态：{warehouse.WarehouseName}，新状态：{input.Status}",
                warehouse.Id,
                warehouse.WarehouseCode,
                warehouse.WarehouseName
            );

            return ObjectMapper.Map<SorehouseModels, StorehouseDto>(warehouse);
        }

        private async Task<bool> IsCurrentUserAdminAsync()
        {
            var currentUser = await _userRepository.GetAsync(CurrentUser.Id.Value);
            // 这里需要根据你的实际需求来判断用户是否是管理员
            // 例如，可以检查用户的角色、权限等
            // 这里简单实现，你需要根据实际情况修改
            return true; // 临时返回 true，你需要实现真实的管理员检查逻辑
        }

        /// <summary>
        /// 删除仓库及其关联的所有库位
        /// </summary>
        public override async Task DeleteAsync(Guid id)
        {
            try
            {
                // 获取仓库信息
                var warehouse = await _repository.GetAsync(id);
                if (warehouse == null)
                {
                    throw new UserFriendlyException($"未找到ID为 {id} 的仓库");
                }

                // 检查仓库状态
                if (warehouse.IsLocked)
                {
                    throw new UserFriendlyException("仓库已锁定，无法删除");
                }

                using (var uow = _unitOfWorkManager.Begin(requiresNew: true))
                {
                    try
                    {
                        // 1. 删除关联的库位
                        await _locationRepository.DeleteAsync(x => x.WarehouseId == id);

                        // 2. 删除仓库
                        await _repository.DeleteAsync(id);

                        // 提交事务
                        await uow.CompleteAsync();
                    }
                    catch (Exception ex)
                    {
                        await uow.RollbackAsync();
                        _logger.LogError(ex, "删除仓库及其库位时发生错误: {Message}", ex.Message);
                        throw new UserFriendlyException($"删除仓库及其库位失败: {ex.Message}");
                    }
                }
            }
            catch (UserFriendlyException)
            {
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "删除仓库时发生错误: {Message}", ex.Message);
                throw new UserFriendlyException($"删除仓库失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 批量删除仓库及其关联的库位
        /// </summary>
        public async Task<BatchDeleteResultDto> BatchDeleteAsync(List<Guid> ids)
        {
            var result = new BatchDeleteResultDto
            {
                TotalCount = ids.Count
            };

            if (ids == null || ids.Count == 0)
            {
                throw new UserFriendlyException("请选择要删除的仓库");
            }

            // 获取所有要删除的仓库信息
            var warehouses = await _repository.GetListAsync(w => ids.Contains(w.Id));
            
            using (var uow = _unitOfWorkManager.Begin(requiresNew: true))
            {
                try
                {
                    foreach (var warehouse in warehouses)
                    {
                        try
                        {
                            // 检查仓库状态
                            if (warehouse.IsLocked)
                            {
                                result.FailedItems.Add(new BatchDeleteResultDto.FailedItem
                                {
                                    Id = warehouse.Id,
                                    WarehouseCode = warehouse.WarehouseCode,
                                    Reason = "仓库已锁定，无法删除"
                                });
                                continue;
                            }

                            // 删除关联的库位
                            await _locationRepository.DeleteAsync(x => x.WarehouseId == warehouse.Id);

                            // 删除仓库
                            await _repository.DeleteAsync(warehouse.Id);

                            // 记录成功
                            result.SuccessIds.Add(warehouse.Id);
                        }
                        catch (Exception ex)
                        {
                            // 记录单个仓库删除失败
                            result.FailedItems.Add(new BatchDeleteResultDto.FailedItem
                            {
                                Id = warehouse.Id,
                                WarehouseCode = warehouse.WarehouseCode,
                                Reason = $"删除失败: {ex.Message}"
                            });
                            _logger.LogError(ex, "删除仓库 {WarehouseCode} 时发生错误: {Message}", 
                                warehouse.WarehouseCode, ex.Message);
                        }
                    }

                    // 更新结果统计
                    result.SuccessCount = result.SuccessIds.Count;
                    result.FailedCount = result.FailedItems.Count;

                    // 如果全部失败，回滚事务
                    if (result.SuccessCount == 0)
                    {
                        await uow.RollbackAsync();
                        throw new UserFriendlyException("所有仓库删除失败，操作已回滚");
                    }

                    // 提交事务
                    await uow.CompleteAsync();

                    return result;
                }
                catch (Exception ex)
                {
                    await uow.RollbackAsync();
                    _logger.LogError(ex, "批量删除仓库时发生错误: {Message}", ex.Message);
                    throw new UserFriendlyException($"批量删除仓库失败: {ex.Message}");
                }
            }
        }

        /// <summary>
        /// 更新仓库及其库位信息
        /// </summary>
        public async Task<StorehouseDto> UpdateWithLocationsAsync(UpdateStorehouseWithLocationsDto input)
        {
            try
            {
                using (var uow = _unitOfWorkManager.Begin())
                {
                    var warehouse = await _repository.GetAsync(input.Id);
                    if (warehouse == null)
                    {
                        throw new UserFriendlyException($"未找到ID为 {input.Id} 的仓库");
                    }

                    try
                    {
                        // 1. 更新仓库基本信息
                        warehouse.WarehouseCode = input.Storehouse.WarehouseCode;
                        warehouse.WarehouseName = input.Storehouse.WarehouseName;
                        warehouse.WarehouseCapacity = input.Storehouse.WarehouseCapacity ?? 0;
                        warehouse.WarehouseAddress = input.Storehouse.WarehouseAddress ?? string.Empty;
                        warehouse.ManagementDept = input.Storehouse.ManagementDept ?? string.Empty;
                        warehouse.WarehouseManager = input.Storehouse.WarehouseManager ?? string.Empty;
                        warehouse.WarehouseStatus = input.Storehouse.WarehouseStatus ?? "正常";
                        warehouse.Phone = input.Storehouse.Phone ?? string.Empty;
                        warehouse.Sort = input.Storehouse.Sort ?? 0;
                        warehouse.IsLocked = input.Storehouse.IsLocked ?? false;
                        warehouse.Remarks = input.Storehouse.Remarks ?? string.Empty;

                        await _repository.UpdateAsync(warehouse);

                        // 记录仓库更新操作日志
                        await _operationLogService.LogOperationAsync(
                            "修改",
                            $"修改仓库及库位信息：{warehouse.WarehouseName}",
                            warehouse.Id,
                            warehouse.WarehouseCode,
                            warehouse.WarehouseName
                        );

                        // 2. 删除指定的库位
                        if (input.LocationIdsToDelete != null && input.LocationIdsToDelete.Count > 0)
                        {
                            await _locationRepository.DeleteAsync(x => 
                                input.LocationIdsToDelete.Contains(x.Id) && 
                                x.WarehouseId == input.Id);
                        }

                        // 3. 更新或添加库位
                        if (input.Locations != null && input.Locations.Count > 0)
                        {
                            foreach (var locDto in input.Locations)
                            {
                                if (string.IsNullOrEmpty(locDto.LocationId))
                                {
                                    throw new UserFriendlyException("库位编码不能为空");
                                }

                                if (string.IsNullOrEmpty(locDto.LocationName))
                                {
                                    throw new UserFriendlyException("库位名称不能为空");
                                }

                                // 如果库位已存在，更新它
                                var existingLocation = await _locationRepository.FirstOrDefaultAsync(x => 
                                    x.LocationId == locDto.LocationId && 
                                    x.WarehouseId == input.Id);

                                if (existingLocation != null)
                                {
                                    // 更新现有库位
                                    existingLocation.LocationName = locDto.LocationName;
                                    existingLocation.Capacity = locDto.Capacity;
                                    existingLocation.Supervisor = locDto.Supervisor ?? string.Empty;
                                    existingLocation.Status = locDto.Status;
                                    existingLocation.SortOrder = locDto.SortOrder;
                                    existingLocation.Remarks = locDto.Remarks ?? string.Empty;

                                    await _locationRepository.UpdateAsync(existingLocation);
                                }
                                else
                                {
                                    // 创建新库位
                                    var location = new locationModel(
                                        GuidGenerator.Create(),
                                        locDto.LocationId,
                                        locDto.LocationName,
                                        locDto.Capacity,
                                        locDto.Supervisor ?? string.Empty,
                                        locDto.Status,
                                        locDto.SortOrder,
                                        locDto.Remarks ?? string.Empty,
                                        warehouse.Id
                                    );

                                    await _locationRepository.InsertAsync(location);
                                }
                            }
                        }

                        // 4. 更新仓库的库位数量
                        var locationCount = await _locationRepository.CountAsync(x => x.WarehouseId == warehouse.Id);
                        warehouse.LocationCount = locationCount;
                        await _repository.UpdateAsync(warehouse);

                        await uow.CompleteAsync();

                        return ObjectMapper.Map<SorehouseModels, StorehouseDto>(warehouse);
                    }
                    catch (Exception ex)
                    {
                        await uow.RollbackAsync();
                        _logger.LogError(ex, "更新仓库和库位时发生错误: {Message}", ex.Message);
                        throw new UserFriendlyException($"更新仓库和库位失败: {ex.Message}");
                    }
                }
            }
            catch (UserFriendlyException)
            {
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新仓库时发生错误: {Message}", ex.Message);
                throw new UserFriendlyException($"更新仓库失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 获取仓库及其库位的详细信息
        /// </summary>
        public async Task<StorehouseWithLocationsDto> GetStorehouseWithLocationsAsync(Guid id)
        {
            try
            {
                // 获取仓库信息
                var warehouse = await _repository.GetAsync(id);
                if (warehouse == null)
                {
                    throw new UserFriendlyException($"未找到ID为 {id} 的仓库");
                }

                // 获取该仓库的所有库位
                var locations = await _locationRepository.GetListAsync(x => x.WarehouseId == id);

                // 创建返回DTO
                var result = new StorehouseWithLocationsDto
                {
                    Storehouse = ObjectMapper.Map<SorehouseModels, StorehouseDto>(warehouse),
                    Locations = ObjectMapper.Map<List<locationModel>, List<locationModelDto>>(locations)
                };

                return result;
            }
            catch (UserFriendlyException)
            {
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取仓库及库位信息时发生错误: {Message}", ex.Message);
                throw new UserFriendlyException($"获取仓库及库位信息失败: {ex.Message}");
            }
        }
    }
}
